package com.sky.Aspect;

/*
* 自定义切面，用于处理需要自动填充的公共字段
* */

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Slf4j
@Aspect
public class AutoFillAspect {


    /*
     * 切面表达式  切点为mapper下的并且 被 AutoFill注解标识  的方法
     * */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void fillCut() {};

    /*前置通知*/
    @Before("fillCut()")
    public void beforeAutoFill(JoinPoint joinPoint){

        // 1. 获取当前被拦截方法操作方法上的数据库操作类型  UPDATE INSERT
        MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature(); // 获取方法签名
        AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class); // 获取方法注解信息
        OperationType operationType = autoFill.value(); // 获取当前方法的操作类型
        log.info("进入自动填充操作！！当前为{}操作",operationType);

        // 2. 获取方法参数 --- 实体对象     这里我们约定：第一个参数为操作实体对象
        Object[] args = joinPoint.getArgs();
        if(args==null || args.length==0){
            return;
        }

        // 3.准备填充的信息
        LocalDateTime now = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();

        // 4.利用反射，获取方法的setting
        Object entity = args[0]; // 获取参数 操作实体对象
        try {
            // 获取实体类的 setting方法
            Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            // INSERT  类型的填充操作
            if(operationType==OperationType.INSERT){
                //  执行实体类赋值方法，进行填充操作
                setCreateTime.invoke(entity,now);
                setCreateUser.invoke(entity,id);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,id);
            } // UPDATE 类型的填充操作
            else{
                //  执行实体类赋值方法，进行填充操作
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,id);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }





}
